﻿#include <SceneViewerFunctions.h>
#include <SceneViewer.h>
#include <osg/ShapeDrawable>
#include <osg/Material>
#include <osg/UserDataContainer>
#include <osgGA/TrackballManipulator>

#include <CoordinateAtCorner.h>
#include <FindNodeByIdVisitor.h>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <NodeInformationContainer.h>

#include <EditorModeManager.h>
#include <FindGUIEventHandlerByIdVisitor.h>
#include <FindCameraManipulatorByIdVisitor.h>
#include <ReplaceDOFVisitor.h>
#include <TransformMatrixVisitor.h>
#include <Orientation.h>

#include <osg/ComputeBoundsVisitor>
#include <osgwTools/Transform.h>
#include <ShowOrHideAllNodeVisitor.h>
#include <FindNodeByNameVisitor.h>
#include <OBBbox.h>
#include <CameraManipulatorIntersection.h>
using namespace SceneViewerFunctions;


osg::Vec4 SceneViewerFunctions::osg_vec4( double r, double g, double b, double a )
{
    osg::Vec4 vec(r, g, b, a);
    return vec;
}

double SceneViewerFunctions::osg_vec3_at( const osg::Vec3& vec, int index )
{
    if (index <= 2 )
    {
        return vec[index];
    }
    else
    {
        return vec[0];
    }
}


osg::Vec3 SceneViewerFunctions::osg_vec3( double x, double y, double z )
{
    osg::Vec3 vec(x, y, z);
    return vec;
}


osg::Vec3 SceneViewerFunctions::osg_matrix_getTrans( const osg::Matrix& m )
{
    return m.getTrans();
}


osg::Vec3 SceneViewerFunctions::osg_matrix_getRotate( const osg::Matrix& m )
{
    //return m.getRotate().asVec3();

    Orientation orient;
    //orient.setBasis(osg::Y_AXIS, osg::X_AXIS, osg::Z_AXIS);
    orient.setBasis(osg::X_AXIS, osg::Y_AXIS, osg::Z_AXIS);
    osg::Vec3 vec = orient.getYPR(m.getRotate());

    double x = vec[0]; /// 180 * osg::PI;
    double y = vec[1]; /// 180 * osg::PI;
    double z = vec[2]; /// 180 * osg::PI;

    {
        //x rangeright
        double t = (x + 180)/360.0;
        int ti = t;
        x = -180+(t-ti)*360;
    }
//    {
//        //y rangeright
//        double t = (x + 180)/360.0;
//        int ti = t;
//        x = -180+(t-ti)*360;
//    }
    {
        //z rangeright
        double t = (z + 180)/360.0;
        int ti = t;
        z = -180+(t-ti)*360;
    }
    return osg::Vec3(x,y,z);
}


osg::Matrix SceneViewerFunctions::osg_matrix_TransRotate(const osg::Vec3& trans, const osg::Vec3& rote )
{
    osg::Matrix m;
    m.setTrans(trans);
    m.setRotate(osg::Quat(rote[0], osg::X_AXIS, rote[1], osg::Y_AXIS, rote[2], osg::Z_AXIS));

    return m;
}

osg::Matrix SceneViewerFunctions::osg_matrix_RotateTrans(const osg::Vec3& rote , const osg::Vec3& trans )
{
    osg::Matrix m_t;
    osg::Matrix m_r;
    osg::Matrix m;
    m_t.setTrans(trans);
    //m_r.setRotate(osg::Quat(rote[0], osg::X_AXIS, rote[1], osg::Y_AXIS, rote[2], osg::Z_AXIS));
    Orientation orient;
    orient.setBasis(osg::Y_AXIS, osg::X_AXIS, osg::Z_AXIS);
    m_r = orient.getMatrix(rote[1]/osg::PI * 180, rote[0]/osg::PI * 180, rote[2]/osg::PI * 180);
    m = m_r*m_t;
    return m;
}
osg::Matrix SceneViewerFunctions::osg_matrix_ScaleRotateTrans(const osg::Vec3 &scale, const osg::Vec3 &rote, const osg::Vec3 &trans)
{
    osg::Matrix m_t;
    osg::Matrix m_r;
    osg::Matrix m_s;
    osg::Matrix m;
    m_t.setTrans(trans);
    //m_r.setRotate(osg::Quat(rote[0], osg::X_AXIS, rote[1], osg::Y_AXIS, rote[2], osg::Z_AXIS));

    Orientation orient;
//    orient.setBasis(osg::Y_AXIS, osg::X_AXIS, osg::Z_AXIS);
//    m_r = orient.getMatrix(rote[1]/osg::PI * 180, rote[0]/osg::PI * 180, rote[2]/osg::PI * 180);
    orient.setBasis(osg::X_AXIS, osg::Y_AXIS, osg::Z_AXIS);
//    double r1 = Orientation::normalizeAngle(rote[0]);
//    double r2 = Orientation::normalizeAngle(rote[1]);
//    double r3 = Orientation::normalizeAngle(rote[2]);

    m_r = orient.getMatrix(rote[0], rote[1], rote[2]);

    m_s.makeScale(scale);

    m = m_s*m_r*m_t;
    return m;

}
void SceneViewerFunctions::setUpSceneData()
{
    SceneViewer::instance()->setUpSceneData();
}

void SceneViewerFunctions::addDefaultTrackBallCameraManipulator( const std::string& name )
{
    osg::ref_ptr<osgGA::TrackballManipulator> camera_manipulator_1 = new osgGA::TrackballManipulator;
    camera_manipulator_1->setName(name);
    SceneViewer::instance()->getSwitchCameraManipulator()->addCameraManipulator(camera_manipulator_1);
}

void SceneViewerFunctions::addCameraManipulatorIntersection(const std::string &name)
{
    osg::ref_ptr<CameraManipulatorIntersection> camera_manipulator = new CameraManipulatorIntersection;
    camera_manipulator->setName(name);
    SceneViewer::instance()->getSwitchCameraManipulator()->addCameraManipulator(camera_manipulator);

}

void SceneViewerFunctions::setUpViewInWindow( int x, int y, int width, int height )
{
    SceneViewer::instance()->getViewer()->setUpViewInWindow( x, y, width, height);
}

osg::Camera* SceneViewerFunctions::getOsgCamera()
{
    return SceneViewer::instance()->getViewer()->getCamera();
}

void SceneViewerFunctions::addOsgNodeToSceneViewer( osg::ref_ptr<osg::Node> node )
{
    SceneViewer::instance()->addChild(node);
}

void SceneViewerFunctions::sceneViewerAddNodeToModelRoot(osg::ref_ptr<osg::Node> node)
{
    SceneViewer::instance()->getModelRoot()->addChild(node);
}

osg::ref_ptr<osg::Node> SceneViewerFunctions::sceneViewerInstance()
{
    return SceneViewer::instance();
}

osg::ref_ptr<osg::Group> SceneViewerFunctions::CreateCoordinate(double scale)
{
    osg::ref_ptr<osg::Group> group = new osg::Group;
    //3 line
    osg::ref_ptr<osg::MatrixTransform> matX = new osg::MatrixTransform;
    osg::ref_ptr<osg::MatrixTransform> matY = new osg::MatrixTransform;
    osg::ref_ptr<osg::MatrixTransform> matZ = new osg::MatrixTransform;
    osg::ref_ptr<osg::Geode> gnode = new osg::Geode;
    gnode->addDrawable(new osg::ShapeDrawable(new osg::Cylinder(osg::Vec3d(0,0,0), scale/10, scale)));
    group->addChild(matX);
    group->addChild(matY);
    group->addChild(matZ);
    matX->addChild(gnode);
    matX->setMatrix(osg::Matrixd::rotate(osg::PI_2, osg::Y_AXIS)*osg::Matrixd::translate(scale/2, 0, 0));
    matY->addChild(gnode);
    matY->setMatrix(osg::Matrixd::rotate(-osg::PI_2, osg::X_AXIS)*osg::Matrixd::translate(0, scale/2, 0));
    matZ->addChild(gnode);
    matZ->setMatrix(osg::Matrixd::translate(0, 0, scale/2));//Z do not need to rotate,Z default.
    //3 Arrow
    osg::ref_ptr<osg::MatrixTransform> matArrowX = new osg::MatrixTransform;
    osg::ref_ptr<osg::MatrixTransform> matArrowY = new osg::MatrixTransform;
    osg::ref_ptr<osg::MatrixTransform> matArrowZ = new osg::MatrixTransform;
    osg::ref_ptr<osg::Geode> arrowGeode = new osg::Geode;
    arrowGeode->addDrawable(new osg::ShapeDrawable(new osg::Cone(osg::Vec3d(0,0,0), scale/5, scale/2)));

    osg::Material* material_X = new osg::Material;
    osg::Material* material_Y = new osg::Material;
    osg::Material* material_Z = new osg::Material;
    group->addChild(matArrowX);
    group->addChild(matArrowY);
    group->addChild(matArrowZ);
    matArrowX->addChild(arrowGeode);
    matArrowX->setMatrix(osg::Matrixd::rotate(osg::PI_2, osg::Y_AXIS)*osg::Matrixd::translate(scale, 0, 0));
    material_X->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0, 0.0, 0.0, 1.0));
    matArrowX->getOrCreateStateSet()->setAttribute(material_X);
    matArrowY->addChild(arrowGeode);
    matArrowY->setMatrix(osg::Matrixd::rotate(-osg::PI_2, osg::X_AXIS)*osg::Matrixd::translate(0, scale, 0));
    material_Y->setDiffuse(osg::Material::FRONT, osg::Vec4(0.0, 1.0, 0.0, 1.0));
    matArrowY->getOrCreateStateSet()->setAttribute(material_Y);
    matArrowZ->addChild(arrowGeode);
    matArrowZ->setMatrix(osg::Matrixd::translate(0, 0, scale));
    material_Z->setDiffuse(osg::Material::FRONT, osg::Vec4(0.0, 0.0, 1.0, 1.0));
    matArrowZ->getOrCreateStateSet()->setAttribute(material_Z);
    return group;
}

void SceneViewerFunctions::addCoordinateToSceneViewer()
{
    //osg::ref_ptr<osgViewer::Viewer> viewer_ptr = SceneViewer::instance()->getViewer();
    //osg::ref_ptr<osg::Camera> camera = new osg::Camera;
    //{
    //	camera->setViewMatrix(osg::Matrix::identity());
    //	camera->setProjectionMatrix(osg::Matrix::identity() );
    //	camera->setRenderOrder(osg::Camera::POST_RENDER);
    //	camera->setClearMask(GL_DEPTH_BUFFER_BIT);
    //	camera->setAllowEventFocus(false);
    //	camera->setViewport(0, 0, 100, 100);
    //	osg::ref_ptr<osg::Node> gnode = CreateCoordinate(2.0);
    //	camera->addChild(gnode);
    //
    //}
    //viewer_ptr->getSceneData()->asGroup()->addChild(camera);

    osg::ref_ptr<CoordinateAtCorner> coordinate = new CoordinateAtCorner;
    SceneViewer::instance()->addChild(coordinate);

}

int SceneViewerFunctions::getCameraVectorSize()
{
    return SceneViewer::instance()->getSwitchCameraManipulator()->getCameraVectorSize();
}

std::string SceneViewerFunctions::getCameraManipulatorName( int index )
{
    return SceneViewer::instance()->getSwitchCameraManipulator()->getCameraManipulatorName(index);
}

void SceneViewerFunctions::cameraFitScene()
{
    osg::Vec3 center = SceneViewer::instance()->getBound().center();
    double radius = SceneViewer::instance()->getBound().radius();
    SceneViewer::instance()->getSwitchCameraManipulator()->setHomePosition(osg::Vec3(3*radius, 0, 0),center,osg::Vec3(0, 0, 1));
    SceneViewer::instance()->getSwitchCameraManipulator()->home(1);


}

osg::ref_ptr<osgGA::CameraManipulator> SceneViewerFunctions::sceneViewerGetCameraManipulator( int index )
{
    return SceneViewer::instance()->getSwitchCameraManipulator()->getCameraManipulatorByIndex(index);
}

osg::ref_ptr<osgGA::CameraManipulator> SceneViewerFunctions::findCameraManipulatorByIdString(const std::string& id_string)
{
    FindCameraManipulatorByIdVisitor visitor;
    visitor.setIdString(id_string);
    visitor.apply(*SceneViewer::instance()->getViewer());
    osg::ref_ptr<osgGA::CameraManipulator> cm_ptr = visitor.getFindedCameraManipulator();
    return cm_ptr;
}

osg::ref_ptr<osg::Node> SceneViewerFunctions::getSceneViewerRootNode()
{
    osg::ref_ptr<osg::Node> root_node = SceneViewer::instance();
    return root_node;
}

osg::ref_ptr<osg::Node> SceneViewerFunctions::getSceneViewerModelRootNode()
{
    osg::ref_ptr<osg::Node> root_node = SceneViewer::instance()->getModelRoot();
    return root_node;

}
void SceneViewerFunctions::clearSceneViewerModelRootNode()
{
    int child_count = SceneViewer::instance()->getModelRoot()->getNumChildren();
    SceneViewer::instance()->getModelRoot()->removeChild(0,child_count);
}

int SceneViewerFunctions::getChildCount( osg::ref_ptr<osg::Node> node_ptr )
{
    osg::Group* group_ptr = dynamic_cast<osg::Group*>(node_ptr.get());
    if (group_ptr != NULL)
    {
        int childe_count = group_ptr->getNumChildren();
        return childe_count;
    }
    return -1;//代表当前节点不是group类型的


}

osg::ref_ptr<osg::Node> SceneViewerFunctions::getChildOfNode( osg::ref_ptr<osg::Node> node_ptr, int index )
{
    osg::ref_ptr<osg::Node> child_node = NULL;
    osg::Group* group_ptr = dynamic_cast<osg::Group*>(node_ptr.get());
    if (group_ptr != NULL)
    {
        child_node = group_ptr->getChild(index);

    }
    return child_node;
}

std::string SceneViewerFunctions::getNodeName( osg::ref_ptr<osg::Node> node_ptr )
{
    std::string node_name;
    if (node_ptr.get() != NULL)
    {
        node_name = node_ptr->getName();
    }
    return node_name;

}

void SceneViewerFunctions::readNodeFromFile( const std::string& file_name )
{
    SceneViewer::instance()->getModelRoot()->addChild(osgDB::readNodeFile(file_name));
}

osg::ref_ptr<osg::Node> SceneViewerFunctions::osgDBReadNodeFile(const std::string& file_name)
{
    osg::ref_ptr<osg::Node> node_ptr = osgDB::readNodeFile(file_name);
    return node_ptr;
}

void SceneViewerFunctions::writeNodeToFile(osg::ref_ptr<osg::Node> node_ptr, const std::string& file_name)
{
    osgDB::Registry::instance()->writeNode(*node_ptr, file_name, osgDB::Registry::instance()->getOptions());

}


std::string SceneViewerFunctions::osgNodeTypeName( osg::ref_ptr<osg::Node> node_ptr )
{
    std::string type_name = typeid(*node_ptr).name();
    return type_name;
}

void SceneViewerFunctions::nodeAddDescription( osg::ref_ptr<osg::Node> node_ptr, const std::string& des_string, const std::string& string_value )
{
    if (node_ptr.get() != NULL)
    {
        osg::UserDataContainer* user_data_container = node_ptr->getOrCreateUserDataContainer();

        NodeInformationContainer* node_information = dynamic_cast<NodeInformationContainer*>(user_data_container);
        if (node_information == NULL)
        {
            node_information = new NodeInformationContainer;
            node_ptr->setUserDataContainer(node_information);
        }
        node_information->setInformation(des_string, string_value);

    }


}

osg::ref_ptr<osg::Node> SceneViewerFunctions::findNodeByIdString( const std::string& id_string )
{
    FindNodeByIdVisitor visitor;
    visitor.setIdString(id_string);
    SceneViewer::instance()->getModelRoot()->accept(visitor);
    return visitor.getFindedNode();
}

void SceneViewerFunctions::setNodeColor( osg::ref_ptr<osg::Node> node_ptr, const osg::Vec4& color )
{
    if (node_ptr != NULL)
    {
        osg::StateSet* state = node_ptr->getOrCreateStateSet();
        osg::Material* material = new osg::Material;
        material->setDiffuse(osg::Material::FRONT_AND_BACK, color );
        state->setAttributeAndModes( material , osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );


    }

}

std::string SceneViewerFunctions::nodeGetDescription( osg::ref_ptr<osg::Node> node_ptr, const std::string& des_string )
{
    std::string str_value;
    if (node_ptr != NULL)
    {
        osg::UserDataContainer* user_data_container = node_ptr->getOrCreateUserDataContainer();

        NodeInformationContainer* node_information = dynamic_cast<NodeInformationContainer*>(user_data_container);
        if (node_information == NULL)
        {
            node_information = new NodeInformationContainer;
            node_ptr->setUserDataContainer(node_information);
        }
        else
        {
            str_value = node_information->getInformation(des_string);
        }


    }
    return str_value;

}


bool SceneViewerFunctions::nodePtrUsable(osg::ref_ptr<osg::Node> node_ptr)
{
    if (node_ptr != NULL)
    {
        return true;
    }
    return false;
}

void SceneViewerFunctions::nodeAddChild(osg::ref_ptr<osg::Node> node_ptr, osg::ref_ptr<osg::Node> child_node_ptr)
{
    osg::ref_ptr<osg::Group> group_ptr = dynamic_cast<osg::Group*>(node_ptr.get());
    if (group_ptr != NULL)
    {
        group_ptr->addChild(child_node_ptr);
    }
}

void SceneViewerFunctions::nodeSetUpdateCallBack(osg::ref_ptr<osg::Node> node_ptr, osg::ref_ptr<osg::NodeCallback> node_call_back)
{
    if (node_ptr != NULL)
    {
        node_ptr->setUpdateCallback(node_call_back);
    }

}


void SceneViewerFunctions::nodeInsertParent( osg::ref_ptr<osg::Node> node_ptr, osg::ref_ptr<osg::Node> parent_node_ptr )
{
    if (node_ptr != NULL && parent_node_ptr != NULL)
    {
        osg::ref_ptr<osg::Group> group_ptr = dynamic_cast<osg::Group*>(parent_node_ptr.get());
        if (group_ptr != NULL)
        {
            osg::ref_ptr<osg::Group> old_parent_ptr = node_ptr->getParent(0);

            old_parent_ptr->addChild(parent_node_ptr);
            group_ptr->addChild(node_ptr);
            old_parent_ptr->removeChild(node_ptr.get());
        }



    }
}


osg::ref_ptr<osg::NodeCallback> SceneViewerFunctions::nodeGetUpdateCallBack( osg::ref_ptr<osg::Node> node_ptr )
{
    osg::ref_ptr<osg::NodeCallback> node_call_back = NULL;
    if (node_ptr != NULL)
    {
        node_call_back = node_ptr->getUpdateCallback();
    }
    return node_call_back;
}


osg::ref_ptr<osg::Node> SceneViewerFunctions::nodeGetParent( osg::ref_ptr<osg::Node> node_ptr )
{
    osg::ref_ptr<osg::Node> parten_node_ptr = NULL;
    if (node_ptr != NULL)
    {
        parten_node_ptr = node_ptr->getParent(0);
    }
    return parten_node_ptr;
}

void SceneViewerFunctions::nodeSetNodeMask(osg::ref_ptr<osg::Node> node_ptr, int node_mask)
{
    if (node_ptr != NULL)
    {
        node_ptr->setNodeMask(node_mask);
    }
}
void SceneViewerFunctions::nodeHide(osg::ref_ptr<osg::Node> node_ptr)
{
    if (node_ptr != NULL)
    {
        node_ptr->setNodeMask(0x0);
    }
}
void SceneViewerFunctions::nodeShow(osg::ref_ptr<osg::Node> node_ptr)
{

    if (node_ptr != NULL)
    {
        osg::Node::NodeMask mask = 0xffffffff;

        node_ptr->setNodeMask(mask);
        //std::cout<<"mask"<<std::endl;
    }
}

bool SceneViewerFunctions::nodeIsShow(osg::ref_ptr<osg::Node> node_ptr)
{
    bool bool_value = false;
    if (node_ptr != NULL)
    {
        int mask = node_ptr->getNodeMask();
        if ( mask == 0 )
        {
            bool_value = false;
        }
        else
        {
            bool_value = true;
        }

    }
    return bool_value;
}

void SceneViewerFunctions::nodeAllShow()
{
    ShowOrHideAllNodeVisitor visitor(true);
    SceneViewerFunctions::getSceneViewerModelRootNode()->accept(visitor);

}
void SceneViewerFunctions::nodeAllHide()
{
    ShowOrHideAllNodeVisitor visitor(false);
    SceneViewerFunctions::getSceneViewerModelRootNode()->accept(visitor);

}

int SceneViewerFunctions::sceneViewerGetEventHandlerSize()
{
    return SceneViewer::instance()->getEventHandlerSize();
}

osg::ref_ptr<osgGA::GUIEventHandler> SceneViewerFunctions::sceneViewerGetEventHandler( int index )
{
    return SceneViewer::instance()->getEventHandler(index);
}

osg::ref_ptr<osg::Object> SceneViewerFunctions::sceneViewerGetEventHandlerObject( int index )
{
    return SceneViewer::instance()->getEventHandlerObject(index);
}


osg::ref_ptr<osg::Object> SceneViewerFunctions::GUIEventHandlerPrtToOsgObjectPtr( osg::ref_ptr<osgGA::GUIEventHandler> handler )
{
    osg::ref_ptr<osg::Object> obj_ptr = dynamic_cast<osgGA::GUIEventHandler*>(handler.get());
    return obj_ptr;
}
osg::ref_ptr<osgGA::GUIEventHandler> SceneViewerFunctions::findGUIEventHandlerByIdString(const std::string& id_string)
{
    FindGUIEventHandlerByIdVisitor visitor;
    visitor.setIdString(id_string);
    visitor.apply(*SceneViewer::instance()->getViewer());
    osg::ref_ptr<osgGA::GUIEventHandler> handler_ptr = visitor.getFindedGUIEventHandler();
    return handler_ptr;

}

std::string SceneViewerFunctions::osgObjectTypeName( osg::ref_ptr<osg::Object> obj_ptr )
{
    std::string type_name;
    if (obj_ptr != NULL)
    {
        type_name = typeid(*obj_ptr).name();
    }
    return type_name;

}

void SceneViewerFunctions::osgObjectAddDescription( osg::ref_ptr<osg::Object> obj_ptr, const std::string& des_string, const std::string& string_value )
{
    if (obj_ptr.get() != NULL)
    {
        osg::UserDataContainer* user_data_container = obj_ptr->getOrCreateUserDataContainer();

        NodeInformationContainer* node_information = dynamic_cast<NodeInformationContainer*>(user_data_container);
        if (node_information == NULL)
        {
            node_information = new NodeInformationContainer;
            obj_ptr->setUserDataContainer(node_information);
        }
        node_information->setInformation(des_string, string_value);

    }

}

std::string SceneViewerFunctions::osgObjectGetDescription( osg::ref_ptr<osg::Object> obj_ptr, const std::string& des_string )
{
    std::string str_value;
    if (obj_ptr != NULL)
    {
        osg::UserDataContainer* user_data_container = obj_ptr->getOrCreateUserDataContainer();

        NodeInformationContainer* node_information = dynamic_cast<NodeInformationContainer*>(user_data_container);
        if (node_information == NULL)
        {
            node_information = new NodeInformationContainer;
            obj_ptr->setUserDataContainer(node_information);
        }
        else
        {
            str_value = node_information->getInformation(des_string);
        }


    }
    return str_value;


}

std::string SceneViewerFunctions::osgObjectName( osg::ref_ptr<osg::Object> obj_ptr )
{
    std::string str_value;
    if (obj_ptr != NULL)
    {
        str_value = obj_ptr->getName();
    }
    return str_value;
}

osg::ref_ptr<osg::Object> SceneViewerFunctions::voidPtrToOsgObjectPtr( void* void_ptr )
{
    osg::Object* void_obj_ptr = (osg::Object*)void_ptr;
    osg::ref_ptr<osg::Object> obj_ptr = dynamic_cast<osg::Object*>(void_obj_ptr);
    return obj_ptr;
}

void* SceneViewerFunctions::osgObjectPtrToVoidPtr( osg::ref_ptr<osg::Object> obj_ptr )
{
    void* void_ptr = obj_ptr.get();
    return void_ptr;
}

void SceneViewerFunctions::editorModeManagerSetEditingNode( osg::ref_ptr<osg::Node> editing_node )
{
    EditorModeManager::instance()->setEditingNode(editing_node);
}

void SceneViewerFunctions::editorModeManagerEnterEditing()
{
    EditorModeManager::instance()->enterEditing();
}

void SceneViewerFunctions::editorModeManagerQuitEditing()
{
    EditorModeManager::instance()->quitEditing();
}

int SceneViewerFunctions::geodeGetDrawableCount( osg::ref_ptr<osg::Geode> geode_ptr )
{
    if (geode_ptr != NULL)
    {
        return geode_ptr->getDrawableList().size();
    }

}

osg::ref_ptr<osg::Drawable> SceneViewerFunctions::geodeGetDrawable( osg::ref_ptr<osg::Geode> geode_ptr, int index )
{
    if (geode_ptr != NULL)
    {

        if (index < geode_ptr->getDrawableList().size() && index >= 0)
        {
            return geode_ptr->getDrawable(index);

        }


    }
    return NULL;
}

osg::ref_ptr<osg::Drawable> SceneViewerFunctions::geodeFindDrawableById(osg::ref_ptr<osg::Geode> geode_ptr, const std::string& id_str)
{
    osg::ref_ptr<osg::Drawable> drawable_ptr = NULL;
    geode_ptr = dynamic_cast<osg::Geode*>(geode_ptr.get());
    if (geode_ptr != NULL)
    {
        int i = 0;
        for (i = 0; i < geode_ptr->getDrawableList().size(); i++)
        {
            drawable_ptr = geode_ptr->getDrawable(i);
            if( osgObjectGetDescription(drawable_ptr, "id") == id_str)
            {
                return drawable_ptr;
            }
        }

    }
    return drawable_ptr;
}

osg::ref_ptr<SkyBox> SceneViewerFunctions::skyBoxNew()
{
    osg::ref_ptr<SkyBox> sky_box = new SkyBox;
    return sky_box;
}

void SceneViewerFunctions::skyBoxSetBackImagePath( osg::ref_ptr<SkyBox> sky_box, const std::string& back_image )
{
    if (sky_box != NULL)
    {
        sky_box->setBackImagePath(back_image);
    }

}

void SceneViewerFunctions::skyBoxSetFrontImagePath( osg::ref_ptr<SkyBox> sky_box, const std::string& front_image )
{
    if (sky_box != NULL)
    {
        sky_box->setFrontImagePath(front_image);
    }

}

void SceneViewerFunctions::skyBoxSetDownImagePath( osg::ref_ptr<SkyBox> sky_box, const std::string& down_image )
{
    if (sky_box != NULL)
    {
        sky_box->setDownImagePath(down_image);
    }

}

void SceneViewerFunctions::skyBoxSetUpImagePath( osg::ref_ptr<SkyBox> sky_box, const std::string& up_image )
{
    if (sky_box != NULL)
    {
        sky_box->setUpImagePath(up_image);
    }

}

void SceneViewerFunctions::skyBoxSetRightImagePath( osg::ref_ptr<SkyBox> sky_box, const std::string& right_image )
{
    if (sky_box != NULL)
    {
        sky_box->setRightImagePath(right_image);
    }

}

void SceneViewerFunctions::skyBoxSetLeftImagePath( osg::ref_ptr<SkyBox> sky_box, const std::string& left_image )
{
    if (sky_box != NULL)
    {
        sky_box->setLeftImagePath(left_image);
    }

}

void SceneViewerFunctions::skyBoxCreat(osg::ref_ptr<SkyBox> sky_box)
{
    if (sky_box != NULL)
    {
        sky_box->createSkyBox();
    }

}


void SceneViewerFunctions::replaceDOFToMatrixTransform(osg::ref_ptr<osg::Node> node_ptr)
{
    ReplaceDOFVisitor replace_dof_vis;
    node_ptr->accept(replace_dof_vis);
    replace_dof_vis.handleDOFVector();
}

osg::Matrix SceneViewerFunctions::transformGetMatrix( osg::ref_ptr<osg::Node> node_ptr )
{
    osg::Matrix m;
    osg::Transform* transform = dynamic_cast<osg::Transform*>(node_ptr.get());
    if (transform != NULL)
    {
        TransformMatrixVisitor trans_m_vis;
        transform->accept(trans_m_vis);
        m = trans_m_vis.getLocalMatrix();
    }
    return m;

}

void SceneViewerFunctions::transformSetMatrix( osg::ref_ptr<osg::Node> node_ptr, osg::Matrix m )
{
    osg::Transform* transform = dynamic_cast<osg::Transform*>(node_ptr.get());
    if (transform != NULL)
    {

        //std::cout<<"matrx changed"<<std::endl;
        TransformMatrixVisitor trans_m_vis;
        trans_m_vis.makeSetMode();
        transform->accept(trans_m_vis);
        trans_m_vis.setLocalMatrix(m);
    }
}


osg::ref_ptr<osg::MatrixTransform> SceneViewerFunctions::matrixTransformNew()
{
    osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform;
    return mt;
}

void SceneViewerFunctions::matrixTransformEliminateScale(osg::ref_ptr<osg::MatrixTransform> mtPtr)
{
    osg::Matrix m = mtPtr->getMatrix();

    osg::Matrix sm;sm.makeScale(m.getScale());
    osg::Matrix rm;rm.makeRotate(m.getRotate());
    osg::Matrix tm;tm.makeTranslate(m.getTrans());

    //m.makeScale(1,1,1);
    m = rm*tm;

    osg::Matrix newM;
    //newM = osg::Matrix::inverse(m);
    //newM *= sm*rm*tm;
    newM *= sm;

    mtPtr->setMatrix(m);
    //std::cout<<"SceneViewerFunctions::matrixTransformEliminateScale num="<<mtPtr->getNumChildren()<<std::endl;
    for(int i=0; i < mtPtr->getNumChildren(); i++)
    {
        osg::Geode* geodePtr = dynamic_cast<osg::Geode*>(mtPtr->getChild(i));
        if(geodePtr != NULL)
        {
            osgwTools::transform(newM, geodePtr);
        }
    }

}

void SceneViewerFunctions::matrixTransformEliminateRotate(osg::ref_ptr<osg::MatrixTransform> mtPtr)
{
    osg::Matrix m = mtPtr->getMatrix();

    osg::Matrix sm;sm.makeScale(m.getScale());
    osg::Matrix rm;rm.makeRotate(m.getRotate());
    osg::Matrix tm;tm.makeTranslate(m.getTrans());

    //m.makeScale(1,1,1);
    m = sm*tm;

    osg::Matrix newM;
    //newM = osg::Matrix::inverse(m);
    //newM *= sm*rm*tm;
    newM *= rm;

    mtPtr->setMatrix(m);
    //std::cout<<"SceneViewerFunctions::matrixTransformEliminateScale num="<<mtPtr->getNumChildren()<<std::endl;
    for(int i=0; i < mtPtr->getNumChildren(); i++)
    {
        osg::Geode* geodePtr = dynamic_cast<osg::Geode*>(mtPtr->getChild(i));
        if(geodePtr != NULL)
        {
            osgwTools::transform(newM, geodePtr);
        }
    }

}
osg::ref_ptr<osg::Object> SceneViewerFunctions::nodeCallBackPtrToOsgObjectPtr( osg::ref_ptr<osg::NodeCallback> call_back )
{
    osg::ref_ptr<osg::Object> obj_ptr = dynamic_cast<osg::Object*>(call_back.get());
    return obj_ptr;
}

osg::ref_ptr<osg::Switch> SceneViewerFunctions::switchNew()
{
    osg::ref_ptr<osg::Switch> switch_ptr = new osg::Switch;
    return switch_ptr;
}

void SceneViewerFunctions::switchSetAllChildrenOn( osg::ref_ptr<osg::Node> node_ptr )
{
    osg::ref_ptr<osg::Switch> switch_ptr = dynamic_cast<osg::Switch*>(node_ptr.get());
    if (switch_ptr != NULL)
    {
        switch_ptr->setAllChildrenOn();
    }

}

void SceneViewerFunctions::switchSetAllChildrenOff( osg::ref_ptr<osg::Node> node_ptr )
{
    osg::ref_ptr<osg::Switch> switch_ptr = dynamic_cast<osg::Switch*>(node_ptr.get());
    if (switch_ptr != NULL)
    {
        switch_ptr->setAllChildrenOff();
    }

}

std::vector<osg::Matrix> SceneViewerFunctions::matrixVectorNew()
{
    std::vector<osg::Matrix> m_v;
    return m_v;
}

void SceneViewerFunctions::matrixVectorAddMatrix( std::vector<osg::Matrix>& m_v, const osg::Matrix& matrix )
{
    m_v.push_back(matrix);
}

osg::Vec3 SceneViewerFunctions::getNodeBoundBoxSize( osg::ref_ptr<osg::Node> node_ptr )
{
    osg::Vec3 size;
    if (node_ptr != NULL)
    {
        osg::ref_ptr<osg::ComputeBoundsVisitor> bound_visitor = new osg::ComputeBoundsVisitor;
        node_ptr->accept(*bound_visitor);

        size[0] = bound_visitor->getBoundingBox().xMax() - bound_visitor->getBoundingBox().xMin();
        size[1] = bound_visitor->getBoundingBox().yMax() - bound_visitor->getBoundingBox().yMin();
        size[2] = bound_visitor->getBoundingBox().zMax() - bound_visitor->getBoundingBox().zMin();


    }
    return size;


}

osg::Vec3 SceneViewerFunctions::getNodeBoundBoxCenter( osg::ref_ptr<osg::Node> node_ptr )
{
    osg::Vec3 center;
    if (node_ptr != NULL)
    {
        osg::ref_ptr<osg::ComputeBoundsVisitor> bound_visitor = new osg::ComputeBoundsVisitor;
        node_ptr->accept(*bound_visitor);

        center[0] = (bound_visitor->getBoundingBox().xMax() + bound_visitor->getBoundingBox().xMin())*0.5;
        center[1] = (bound_visitor->getBoundingBox().yMax() + bound_visitor->getBoundingBox().yMin())*0.5;
        center[2] = (bound_visitor->getBoundingBox().zMax() + bound_visitor->getBoundingBox().zMin())*0.5;


    }
    return center;

}

osg::ref_ptr<osg::Node> SceneViewerFunctions::findNodeByName(const std::string &nodeName)
{
    osg::ref_ptr<osg::Node> modelRoot = SceneViewer::instance()->getModelRoot();
    FindNodeByNameVisitor visitor;
    visitor.setNodeName(nodeName);
    modelRoot->accept(visitor);
    osg::ref_ptr<osg::Node> findedNode = visitor.getFindedNode();
    return findedNode;
}

osg::ref_ptr<osg::Vec3Array> SceneViewerFunctions::computeObbIgnoreSubSubChildNode(osg::ref_ptr<osg::Node> node_ptr)
{
    osg::Group* mtPtr = dynamic_cast<osg::Group*>(node_ptr.get());
    osg::ref_ptr<osg::Vec3Array> obbArray;
    if(mtPtr != NULL)
    {
        osg::ref_ptr<osg::Vec3Array> vertPosArray = new osg::Vec3Array();
        for(int i=0; i < mtPtr->getNumChildren(); i++)
        {
            osg::Geode* geodePtr = dynamic_cast<osg::Geode*>(mtPtr->getChild(i));
            if(geodePtr != NULL)
            {
                for(int j=0; j<geodePtr->getNumDrawables(); j++)
                {
                    osg::Geometry* geom = geodePtr->getDrawable( j )->asGeometry();
                    if( geom != NULL )
                    {
                        // Transform the vertices by the specified matrix.
                        osg::Vec3Array* v = dynamic_cast< osg::Vec3Array* >( geom->getVertexArray() );
                        for(int vIndex = 0 ; vIndex < v->size(); vIndex++)
                        {
                            vertPosArray->push_back(v->at(vIndex));
                        }
                    }
                }
            }
        }
        obbArray = OBBBox::GetOBBCorner(vertPosArray);
    }
    return obbArray;
}



